const ejs = require('ejs')
const path = require('path')
const fs = require('fs')
const { program } = require('commander')
const json2xls = require('json2xls');

const compile = (templateName,data)=>{
    const templatePosition = `../templates/${templateName}`
    const templatePath = path.resolve(__dirname,templatePosition)
    return new Promise((resolve,reject)=>{
        ejs.renderFile(templatePath,{data},{},(err,result)=>{
            if(err){
                console.log(err)
                reject(err)
                return;
            }
            resolve(result)
        })
    })
}

const wiriteToFile = async (pathname,content)=>{
    // let lastIndexOf = path.lastIndexOf('\\')
    // let dir = path.substring(0,lastIndexOf)
    let dir = path.dirname(pathname)
    return fs.promises.mkdir(dir, { recursive: true }).then(()=>{
       return fs.promises.writeFile(pathname,content)
    },()=>{
        console.err("创建路径："+dir+"失败！")
        return fs.promises.writeFile(pathname,content)
    })
}

const getConfigContent = (name)=>{
    //1.读取配置文件的内容
    let scriptPath = program._scriptPath;
    let targetConfigPath = scriptPath.replace('index.js','lib\\config\\'+name)
    let targetContent = fs.readFileSync(targetConfigPath,{encoding:'utf8'})
    return targetContent?.trim();
}
const setConfigContent = (name,content)=>{
    let scriptPath = program._scriptPath;
    let targetConfigPath = scriptPath.replace('index.js','lib\\config\\'+name)
    fs.promises.writeFile(targetConfigPath,content).then(res=>{
        console.log("配置成功,新的后台地址是："+content)
    },err=>{
        console.log("配置失败")
    })
}

const getFiles = (dirPath)=>{
    const files = []; // 存放所有文件路径的数组
    try {
        const dirEntries = fs.readdirSync(dirPath); // 同步读取指定目录下的所有文件和子目录
        
        for (let entry of dirEntries) {
            const filePath = path.join(dirPath, entry); // 将当前目录与文件名或子目录合并为完整路径
            
            if (fs.statSync(filePath).isDirectory()) { // 判断是否为子目录
                files.push(...getFiles(filePath)); // 若是子目录则递归调用自身处理子目录内容
            } else {
                files.push(filePath); // 若不是子目录则直接添加到files数组中
            }
        }
    } catch (err) {
        console.error(`Error reading directory ${dirPath}:`, err);
    }
    
    return files;
}
const compileJava = (java)=>{
    const validInfo = java.match(/^public\s*[\D\d]*\}$/mg)?.[0]||''
    const propsRaw = validInfo?.match(/\/\*\*[\D\d]+?;\s+/mg) //这里?表示取消贪婪模式
    
    const props = propsRaw.map(item=>{
        let propsElements = item.split(/\s+/)
            // [
            //     '/**',         '*',
            //     '流程编号1',   '*',
            //     '<<1232122,',  '*',
            //     '32dsa,322>>', '*/',
            //     'private',     'String',
            //     'processno;',  ''
            // ]
        //1.获取label
        let firstValidIndex = propsElements.indexOf('/**')
        let label = propsElements?.[firstValidIndex+2]
        let spanIndex = label.indexOf('<<')
        if(label.indexOf('<<')>-1){
            label = label.substring(0,spanIndex)
        }
        //2.获取字段名
        let prop = propsElements?.[propsElements.length-2]?.replace(';','')
        //3.获取字段类型
        let javatype = propsElements?.[propsElements.length-3]
        //4.获取配置项
        let containConfigIndexStart = -1;
        let containConfigIndexEnd = -1;
        let config = ''
        propsElements.forEach((element,index) => {
            if(element.indexOf('<<')>-1){
                containConfigIndexStart = index;
            }
            if(element.indexOf('>>')>-1){
                containConfigIndexEnd = index;
            }
        });
        propsElements.forEach((element,index) => {
            if(index>=containConfigIndexStart && index<=containConfigIndexEnd && element!='' &&  element!='*'){
                config+=element;
            }
        });
        //5.判断该字段用哪个组件（input还是select还是date等）//这里对componenttype赋予初值，在getPageConfigFromPropsConfig中会对componenttype再次判断
        let componenttype = 'input'
        let selectOptions = undefined
        if(label.indexOf('日期')>-1 || label.indexOf('时间')>-1){
            componenttype = 'time'
        }else if(label.indexOf('是否')>-1){
            componenttype = 'select'
            selectOptions = [
                {label:'是',value:'1'},
                {label:'否',value:'0'}
            ]
        }
        //...
        //6.返回这些配置，在ejs中使用

        config = config.match(/\<\<[\D\d]+?\>\>/g)?.[0]||''
        return {
            label,
            prop,
            javatype,
            config,
            componenttype,
            selectOptions
        }
    })
    return props
}

const getPageConfigFromPropsConfig = (apipart,propsResult=[],pageName="新页面")=>{
    const _getComponentType=(config)=>{
        if(config.indexOf("code")>-1){
            return 'select'
        }else if(config.indexOf("time")>-1){
            return 'time'
        }
    }
    const _compileConfig = (config,type)=>{
        //参数:<<search[like],table,add,edit,view>>
        if(type=='search'){
            return {queryMethod:'like'}
        }else if(type=='table'){
    
        }else if(type=='add'){
    
        }else if(type=='edit'){
    
        }else if(type=='view'){
    
        }
        return {}
    }
    //1.定义返回的对象
    let pageConfig = {}
    //2.定义页面的apipart和lowername
    pageConfig.pagename = pageName
    pageConfig.apipart = apipart
    pageConfig.lowername = apipart.replace(/[\_-]+/g,'').toLowerCase().trim()
    //3.定义searchConfig
    pageConfig.searchConfig = function(){//如果用户定义了(<<xxx>>有search,那么使用用户定义的,如果没有定义,智能取一个)
        let searchConfig = propsResult.filter(item=>item.config && item.config?.indexOf('search')>-1)
        if(searchConfig.length>0){
            return searchConfig.map(item=>{
                return {
                    label:item.label,
                    prop:item.prop,
                    javatype:item.javatype,
                    _config: item.config,
                    componenttype:_getComponentType(item.config)||item.componenttype,
                    selectOptions:item.selectOptions,
                    config:_compileConfig(item.config,'search')
                }
            })
        }else{
            let searchConfig = propsResult.find(item=>item.label.indexOf('名')>-1 || item.prop.indexOf('name')>-1)
            if(searchConfig){
                return [
                    {
                        label: searchConfig.label,
                        prop: searchConfig.prop,
                        javatype: searchConfig.javatype,
                        _config: searchConfig.config,
                        componenttype:_getComponentType(searchConfig.config)||searchConfig.componenttype,
                        selectOptions:searchConfig.selectOptions,
                        config:_compileConfig(searchConfig.config,'search')
                    }
                ]
            }else{
                searchConfig = propsResult.find(item=>item.prop.indexOf('id') == -1 && item.prop.indexOf('code') == -1)
                if(searchConfig){
                    return [
                        {
                            label: searchConfig.label,
                            prop: searchConfig.prop,
                            javatype: searchConfig.javatype,
                            _config: searchConfig.config,
                            componenttype:_getComponentType(searchConfig.config)||searchConfig.componenttype,
                            selectOptions:searchConfig.selectOptions,
                            config:_compileConfig(searchConfig.config,'search')
                        }
                    ]
                }
            }
        }
    }();
    //4.定义tableConfig
    pageConfig.tableConfig = function(){//如果用户定义了(<<xxx>>有table,那么使用用户定义的,如果没有定义,智能取一个)
        let tableConfig = propsResult.filter(item=>item.config && item.config?.indexOf('table')>-1)
        if(tableConfig.length>0){
            return tableConfig.map(item=>{
                return {
                    label:item.label,
                    prop:item.prop,
                    javatype: item.javatype,
                    _config: item.config,
                    componenttype:_getComponentType(item.config)||item.componenttype,
                    selectOptions:item.selectOptions,
                    config:_compileConfig(item.config,'table')
                }
            })
        }else{
            return propsResult.map(item=>{
                return {
                    label:item.label,
                    prop:item.prop,
                    javatype: item.javatype,
                    _config: item.config,
                    componenttype:_getComponentType(item.config)||item.componenttype,
                    selectOptions:item.selectOptions,
                    config:_compileConfig(item.config,'table')
                }
            })
        }
    }();
    //5.定义addConfig
    pageConfig.addConfig = function(){//如果用户定义了(<<xxx>>有table,那么使用用户定义的,如果没有定义,智能取一个)
        let addConfig = propsResult.filter(item=>item.config && item.config?.indexOf('add')>-1)
        if(addConfig.length>0){
            return addConfig.map(item=>{
                return {
                    label:item.label,
                    prop:item.prop,
                    javatype: item.javatype,
                    _config: item.config,
                    componenttype:_getComponentType(item.config)||item.componenttype,
                    selectOptions:item.selectOptions,
                    config:_compileConfig(item.config,'table')
                }
            })
        }else{
            return propsResult.map(item=>{
                return {
                    label:item.label,
                    prop:item.prop,
                    javatype: item.javatype,
                    _config: item.config,
                    componenttype:_getComponentType(item.config)||item.componenttype,
                    selectOptions:item.selectOptions,
                    config:_compileConfig(item.config,'table')
                }
            })
        }
    }();
    //6.定义detailConfig
    pageConfig.detailConfig = function(){//如果用户定义了(<<xxx>>有table,那么使用用户定义的,如果没有定义,智能取一个)
        let detailConfig = propsResult.filter(item=>item.config && item.config?.indexOf('detail')>-1)
        if(detailConfig.length>0){
            return detailConfig.map(item=>{
                return {
                    label:item.label,
                    prop:item.prop,
                    javatype: item.javatype,
                    _config: item.config,
                    componenttype:_getComponentType(item.config)||item.componenttype,
                    selectOptions:item.selectOptions,
                    config:_compileConfig(item.config,'detail')
                }
            })
        }else{
            return propsResult.map(item=>{
                return {
                    label:item.label,
                    prop:item.prop,
                    javatype: item.javatype,
                    _config: item.config,
                    componenttype:_getComponentType(item.config)||item.componenttype,
                    selectOptions:item.selectOptions,
                    config:_compileConfig(item.config,'detail')
                }
            })
        }
    }();
    //7.定义editConfig
    pageConfig.editConfig = function(){//如果用户定义了(<<xxx>>有table,那么使用用户定义的,如果没有定义,智能取一个)
        let editConfig = propsResult.filter(item=>item.config && item.config?.indexOf('edit')>-1)
        if(editConfig.length>0){
            return editConfig.map(item=>{
                return {
                    label:item.label,
                    prop:item.prop,
                    javatype: item.javatype,
                    _config: item.config,
                    componenttype:_getComponentType(item.config)||item.componenttype,
                    selectOptions:item.selectOptions,
                    config:_compileConfig(item.config,'edit')
                }
            })
        }else{
            return propsResult.map(item=>{
                return {
                    label:item.label,
                    prop:item.prop,
                    javatype: item.javatype,
                    _config: item.config,
                    componenttype:_getComponentType(item.config)||item.componenttype,
                    selectOptions:item.selectOptions,
                    config:_compileConfig(item.config,'edit')
                }
            })
        }
    }();
    return pageConfig;
    //8.定义otherConfig
    //根据解析java后获得的数组,生成searchConfig,tableConfig,addConfig,detailConfig,editConfig,otherConfig
    // [
    //     { label: '承包商id', prop: 'contractorid', type: 'String', config: '' },
    //     {
    //         label: '承包商姓名',
    //         prop: 'contractorname',
    //         type: 'String',
    //         config: '<<search[like],table,add,edit,view>>'
    //     },
    //      .....
    // ]
    //生成
    // {
    //     searchConfig:[
    //         {
    //             label:'承包商姓名',
    //             prop:'contractorname',
    //             type:'String',
    //             rawConfig:'<<search[like],table,add,edit,view>>',
    //                  config:{
    //
    //              }
    //         }
    //     ],
    //     tableConfig:[
    //         {
    //             label:'承包商姓名',
    //             prop:'contractorname',
    //             type:'String',
    //             rawConfig:'<<table,add,edit,view>>'
    //         }
    //     ],
    //     addConfig:[
    //         {
    //             label:'承包商姓名',
    //             prop:'contractorname',
    //             type:'String',
    //             rawConfig:'<<add,edit,view>>'
    //         }
    //     ]
    //     detailConfig:[
    //         {
    //             label:'承包商姓名',
    //             prop:'contractorname',
    //             type:'String',
    //             rawConfig:'<<detail,view>>'
    //         }
    //     ],
    //     editConfig:[
    //         {
    //             label:'承包商姓名',
    //             prop:'contractorname',
    //             type:'String',
    //             rawConfig:'<<edit,view>>'
    //         }
    //     ]
    // }
}
function getDateTimeString() {
    const now = new Date();
    const year = now.getFullYear();
    const month = (now.getMonth() + 1).toString().padStart(2, '0');
    const day = now.getDate().toString().padStart(2, '0');
    const hours = now.getHours().toString().padStart(2, '0');
    const minutes = now.getMinutes().toString().padStart(2, '0');
    const seconds = now.getSeconds().toString().padStart(2, '0');
    return `${year}${month}${day}${hours}${minutes}${seconds}`;
}
function arr2Excel(arr,titleMap,targetFileName="导出结果.xlsx"){
    //map:{name:"姓名",age:"年龄"}
    const jsonArray = [];
    arr.forEach(function(item){
        let obj = {};
        for(let key in item){
            if(titleMap?.[key]){
                obj[titleMap[key]] = item[key];
            }else{
                obj[key] = item[key];
            }
        }
        jsonArray.push(obj);
    });
    
    let xls = json2xls(jsonArray);
    
    fs.writeFileSync(targetFileName, xls, 'binary');
    console.log("导出成功")
}
module.exports = {
    compile,
    wiriteToFile,
    getConfigContent,
    setConfigContent,
    getFiles,
    compileJava,
    getPageConfigFromPropsConfig,
    getDateTimeString,
    arr2Excel
}






